package cn.backpackerxl.easyJDBC.main;

import cn.backpackerxl.easyJDBC.util.*;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Author: backpackerxl
 * CreateTime: 2022/5/13
 * FileName: Generation
 **/
public class Generation {

    private Generation() {
    }

    private static final Map<String, List<DescTable>> listMap = new HashMap<>();

    public static void generationTable(Class<?> clazz) {
        String tableName = SqlFactory.getTableName(clazz);
        Field[] fields = clazz.getDeclaredFields();
        String sql = SqlFactory.getTableSql(fields, tableName);
        Executor.doExecutorSQLUtil(sql);
    }

    public static Config generationEntity(String... filterTable) {
        List<String> tables = BasicQuery.getTables();
        tables.removeAll(Arrays.asList(filterTable));
        for (String table : tables) {
            listMap.put(table, BasicQuery.descByTable(table));
        }
        return new Config();
    }

    public static Config generationService() {
        return new Config();
    }

    /**
     * 创建实体
     *
     * @param config
     */
    public static void build(Config config) {
        String path = config.getPackName().replace(".", "\\");
        createFile(config, path);
        listMap.forEach((key, value) -> writeFile(path, config, key, value));
    }

    /**
     * 生成服务
     *
     * @param config
     */
    public static void buildService(Config config) {
        Set<Class<?>> classes = CreateTable.getClasses(config.getPackName());
        String path = config.getOutName().replace(".", "\\");
        createFile(config, path);
        createFile(config, path + "\\impl");
        createFile(config, config.getDaoPack().replace(".", "\\"));
        classes.forEach(val -> writeFile(path, config, val));
    }

    /**
     * 创建文件并写入内容
     *
     * @param path
     * @param config
     * @param val
     */
    private static void writeFile(String path, Config config, Class<?> val) {
        String[] file = val.getName().split("[.]");
        String fileName = file[file.length - 1] + "Service";
        String fileDao = file[file.length - 1] + "Dao";
        try {
            BufferedWriter writer = new BufferedWriter(new FileWriter(config.getOutURL() + path + "\\" + fileName + ".java"));
            BufferedWriter writerImpl = new BufferedWriter(new FileWriter(config.getOutURL() + path + "\\impl" + "\\" + fileName + "Impl" + ".java"));
            BufferedWriter writerDao = new BufferedWriter(new FileWriter(config.getOutURL() + config.getDaoPack().replace(".", "\\") + "\\" + fileDao + ".java"));
            String desc = config.getDescription().replace("${fileName}", fileName).replace("${Date}", new SimpleDateFormat(Time.yyyyMMdd.get()).format(new Date()));
            String descImpl = config.getDescription().replace("${fileName}", fileName + "Impl").replace("${Date}", new SimpleDateFormat(Time.yyyyMMdd.get()).format(new Date()));
            String descDao = config.getDescription().replace("${fileName}", fileDao).replace("${Date}", new SimpleDateFormat(Time.yyyyMMdd.get()).format(new Date()));
            writer.write("package " + config.getOutName() + ";\n" + BasicService.autoImport(val) + desc + "\n" + "public interface " + fileName + " {\n" + BasicService.save(val) + BasicService.update(val) + BasicService.remove() + BasicService.findById(val) + BasicService.findAll(val) + "}");
            String fileDaoName = fileDao.toLowerCase(Locale.ROOT);
            String autoDao = "private final " + fileDao + " " + fileDaoName + " = (" + fileDao + ") new EasyJDBCRepository(" + fileDao + ".class).init();";
            writer.close();
            writerImpl.write("package " + config.getOutName() + ".impl;\n" + BasicServiceImpl.autoImport(val, config.getOutName(), config.getDaoPack(), fileDao, fileName) + descImpl + "\n" + "public class " + fileName + "Impl" + " implements " + fileName + " {\n\t" + autoDao + "\n\n" + BasicServiceImpl.save(val, fileDaoName) + BasicServiceImpl.update(val, fileDaoName) + BasicServiceImpl.remove(fileDaoName) + BasicServiceImpl.findById(val, fileDaoName) + BasicServiceImpl.findAll(val, fileDaoName) + "}");
            writerImpl.close();
            writerDao.write("package " + config.getDaoPack() + ";\n" + BasicServiceImpl.autoImport(val) + descDao + "\n" + "public interface " + fileDao + " extends EasyJDBCRef<" + BasicEntity.type(val.getName()) + "> {\n}");
            writerDao.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建文件夹
     *
     * @param config
     * @param path
     */
    private static void createFile(Config config, String path) {
        File file = new File(config.getOutURL() + path);
        if (!file.exists()) {
            boolean mkdirs = file.mkdirs();
            if (mkdirs) {
                Logger.logger("create file success.");
            } else {
                Logger.error("create file error.");
            }
        }
    }

    /**
     * 创建文件并写入内容
     *
     * @param path
     * @param config
     * @param name
     * @param value
     */
    private static void writeFile(String path, Config config, String name, List<DescTable> value) {
        try {
            StringBuilder fields = new StringBuilder();
            StringBuilder methods = new StringBuilder();
            StringBuilder title = new StringBuilder();
            title.append("value=\"").append(name.trim()).append("\",");
            if (config.isSetDev()) {
                title.append("dev = true").append(",");
            }
            if (config.isSetShow()) {
                title.append("show = true").append(",");
            }
            String autoImport = BasicEntity.autoImport();
            boolean isAddDate = false;
            for (DescTable descTable : value) {
                Class<?> clazz = config.isBuildType() && descTable.getClasses()[1] != null ? descTable.getClasses()[1] : descTable.getClasses()[0];
                IdType idType = Objects.equals(descTable.getAuto(), "auto_increment") ? IdType.AUTO : IdType.SNOWFLAKE;
                fields.append(BasicEntity.filed(descTable.getName(), clazz, descTable.isKey(), idType)).append("\n");
                methods.append(BasicEntity.getMethod(descTable.getName(), clazz)).append("\n\n").append(BasicEntity.setMethod(descTable.getName(), clazz)).append("\n\n");
                if (clazz.equals(Date.class)) {
                    isAddDate = true;
                }
            }
            autoImport = isAddDate ? autoImport + "\nimport java.util.Date;\n" : autoImport;
            String fileName = StringUtil.headBig(name.trim().replace("t_", ""));
            BufferedWriter writer = new BufferedWriter(new FileWriter(config.getOutURL() + path + "\\" + fileName + ".java"));
            String desc = config.getDescription().replace("${fileName}", name).replace("${Date}", new SimpleDateFormat(Time.yyyyMMdd.get()).format(new Date()));
            String tv = title.toString();
            writer.write("package " + config.getPackName() + ";\n" + autoImport + desc + "\n@Table(" + tv.substring(0, tv.length() - 1) + ")" + "\npublic class " + fileName + " {\n" + fields + "\n" + methods + BasicEntity.toJSON() + "\n}");
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
